home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / othergnu / ispell.zoo / ispell.el < prev    next >
Encoding:
Text File  |  1990-03-06  |  25.5 KB  |  572 lines

  1. ;; ISPELL.EL -- Spelling correction interface for GNU EMACS using "ispell".
  2. ;; Copyright (C) 1988 Ashwin Ram.
  3. ;;
  4. ;; This file is not part of the GNU Emacs distribution (yet).
  5. ;;
  6. ;; This file is distributed in the hope that it will be useful,
  7. ;; but WITHOUT ANY WARRANTY.  No author or distributor
  8. ;; accepts responsibility to anyone for the consequences of using it
  9. ;; or for whether it serves any particular purpose or works at all,
  10. ;; unless he says so in writing.  Refer to the GNU Emacs General Public
  11. ;; License for full details.
  12.  
  13. ;; Everyone is granted permission to copy, modify and redistribute
  14. ;; this file, but only under the conditions described in the
  15. ;; GNU Emacs General Public License.   A copy of this license is
  16. ;; supposed to have been given to you along with GNU Emacs so you
  17. ;; can know your rights and responsibilities.  It should be in a
  18. ;; file named COPYING.  Among other things, the copyright notice
  19. ;; and this notice must be preserved on all copies.
  20.  
  21. (provide 'ispell)
  22.  
  23. ;; Comments, corrections, and improvements should be sent to:
  24. ;;
  25. ;;     Ashwin Ram
  26. ;;
  27. ;;     ARPA:   Ram-Ashwin@cs.yale.edu
  28. ;;     UUCP:   {decvax,ucbvax,harvard,cmcl2,...}!yale!Ram-Ashwin
  29. ;;     BITNET: Ram@yalecs
  30.  
  31.  
  32. ;;; MODIFICATION HISTORY:
  33.  
  34. ;;; Ray Moody       ARPA:    ray@maxwell.physics.purdue.edu
  35. ;;;                 UUCP:    ...!pur-phy!ray
  36. ;;;                 BITNET:  moody@purccvm  (going away soon....)
  37. ;;; Inserted a missing save-excursion in ispell-check-version-compatibility.
  38. ;;; 3/30/89.
  39.  
  40. ;;; Ashwin Ram      ARPA:    Ram-Ashwin@cs.yale.edu
  41. ;;;                 UUCP:    ...!{decvax, linus, seismo}!yale!Ram-Ashwin
  42. ;;;                 BITNET:  Ram@yalecs
  43. ;;; Added flag to allow filters that don't produce single column output.
  44. ;;; 3/20/88.
  45. ;;; Added version compatibility code because of all the confusion.
  46. ;;; 11/19/87.
  47. ;;; Added variable to control embedded word checking (nice in troff but a pain otherwise).
  48. ;;; 10/26/87.
  49. ;;; Interactive word completion.
  50. ;;; 8/14/87.
  51. ;;; Detex before checking spelling.
  52. ;;; Made options more mnemonic, prompt and error messages better.
  53. ;;; Added highlighting of misspelled word.
  54. ;;; Query-replace all occurrences of misspelled word through buffer.
  55. ;;; Allow customization of personal dictionary.
  56. ;;; Moved temporary file to /tmp.
  57. ;;; Added check for dead ispell process to avoid infinite loop.
  58. ;;; Avoid repeated querying for same word in same buffer.
  59. ;;; 7/6/87.
  60.  
  61. ;;; Walt Buehring
  62. ;;; Texas Instruments - Computer Science Center
  63. ;;; ARPA:  Buehring%TI-CSL@CSNet-Relay
  64. ;;; UUCP:  {smu, texsun, im4u, rice} ! ti-csl ! buehring
  65.  
  66. ;;; ispell-region and associated routines added by
  67. ;;; Perry Smith
  68. ;;; pedz@bobkat
  69. ;;; Tue Jan 13 20:18:02 CST 1987
  70.  
  71. ;;; extensively modified by Mark Davies and Andrew Vignaux
  72. ;;; {mark,andrew}@vuwcomp
  73. ;;; Sun May 10 11:45:04 NZST 1987
  74.  
  75. ;;; Depends on the ispell program snarfed from MIT-PREP in early 1986.
  76.  
  77. ;;; CUSTOMIZATION:
  78.  
  79. ;;; To fully install this, add this file to your GNU lisp directory and 
  80. ;;; compile it with M-X byte-compile-file.  Then add the following to the
  81. ;;; appropriate init file:
  82. ;;;     (autoload 'ispell-word "ispell" "Check spelling of word at or before point" t)
  83. ;;;     (autoload 'ispell-complete-word "ispell" "Complete word at or before point" t)
  84. ;;;     (autoload 'ispell-region "ispell" "Check spelling of every word in the region" t)
  85. ;;;     (autoload 'ispell-buffer "ispell" "Check spelling of every word in the buffer" t)
  86.  
  87. ;;; You might want to bind ispell-word and ispell-complete word to keys.
  88. ;;; You might also want to set the ispell customization variables, e.g.:
  89. ;;;     (setq-default ispell-words-have-boundaries t)  ;; To change the default value.
  90. ;;; or, (setq ispell-words-have-boundaries t)          ;; To change a local value (perhaps inside a mode hook).
  91. ;;; Look at variables starting with "ispell-" to see what you get.
  92.  
  93. ;;; If run on a heavily loaded system, the initial sleep time in ispell-init-process
  94. ;;; may need to be increased.
  95.  
  96. ;;; If you count special characters like ' (apostrophe) or - (hyphen) as part of
  97. ;;; a word, set their syntax table entries as follows:
  98. ;;;     (modify-syntax-entry ?' "w   " ispell-syntax-table)
  99. ;;;     (modify-syntax-entry ?- "w   " ispell-syntax-table)
  100. ;;; Similarly, if you don't want something to count as a word character, set its
  101. ;;; syntax entry to ".   ".
  102.  
  103. (defconst ispell-version "2.0.01") ;; Check against output of "ispell -v".
  104.  
  105. (defconst ispell-out-name " *ispell*"
  106.   "Name of the buffer that is associated with the 'ispell' process")
  107.  
  108. (defconst ispell-temp-name " *ispell-temp*"
  109.   "Name of the temporary buffer that 'ispell-region' uses to hold the
  110. filtered region")
  111.  
  112. (defvar ispell-program-name "ispell"
  113.   "*Program invoked by ispell-word and ispell-region commands.")
  114.  
  115. (defvar ispell-dictionary
  116.    nil
  117.    "*Personal dictionary file containing a list of words, one to a line.
  118. If nil, defaults to ispell's normal default (usually ~/.ispell_words).")
  119.  
  120. (defvar ispell-words-have-boundaries t
  121.    "*If nil, a misspelled word matches embedded words too.  This is useful in
  122. nroff/troff, where a misspelled word may be hidded (e.g., \fIword\fB), and a
  123. pain otherwise.")
  124.  
  125. (defvar ispell-highlight nil
  126.    "*If non-nil, misspelled words are highlighted.  See the function highlight-region.")
  127.  
  128. (defvar ispell-syntax-table nil
  129.    "*Syntax table used by ispell to find word boundaries.  You may change syntax
  130. entries to, say, allow ' and - to be part of words, or not, as you prefer.")
  131.  
  132. (if (null ispell-syntax-table)
  133.     ;; The following assumes that the standard-syntax-table
  134.     ;; is static.  If you add words with funky characters
  135.     ;; to your dictionary, the following may have to change.
  136.     (progn
  137.       (setq ispell-syntax-table (make-syntax-table))
  138.       ;; Make certain characters word constituents
  139.       ;; (modify-syntax-entry ?' "w   " ispell-syntax-table)
  140.       ;; (modify-syntax-entry ?- "w   " ispell-syntax-table)
  141.       ;; Get rid on existing word syntax on certain characters 
  142.       (modify-syntax-entry ?0 ".   " ispell-syntax-table)
  143.       (modify-syntax-entry ?1 ".   " ispell-syntax-table)
  144.       (modify-syntax-entry ?2 ".   " ispell-syntax-table)
  145.       (modify-syntax-entry ?3 ".   " ispell-syntax-table)
  146.       (modify-syntax-entry ?4 ".   " ispell-syntax-table)
  147.       (modify-syntax-entry ?5 ".   " ispell-syntax-table)
  148.       (modify-syntax-entry ?6 ".   " ispell-syntax-table)
  149.       (modify-syntax-entry ?7 ".   " ispell-syntax-table)
  150.       (modify-syntax-entry ?8 ".   " ispell-syntax-table)
  151.       (modify-syntax-entry ?9 ".   " ispell-syntax-table)
  152.       (modify-syntax-entry ?$ ".   " ispell-syntax-table)
  153.       (modify-syntax-entry ?% ".   " ispell-syntax-table)))
  154.  
  155.  
  156. (defun ispell-word (&optional quietly)
  157.    "Check spelling of word at or before dot.
  158. If word not found in dictionary, display possible corrections in a window 
  159. and let user select."
  160.    (interactive)
  161.    (let* ((current-syntax (syntax-table))
  162.           start end word poss replace)
  163.       (unwind-protect
  164.             (save-excursion
  165.                (set-syntax-table ispell-syntax-table)            ;; Ensure syntax table is reasonable 
  166.                (if (not (looking-at "\\w"))
  167.                    (re-search-backward "\\w" (point-min) 'stay)) ;; Move backward for word if not already on one
  168.                (re-search-backward "\\W" (point-min) 'stay)      ;; Move to start of word
  169.                (or (re-search-forward "\\w+" nil t)              ;; Find start and end of word
  170.                    (error "No word to check."))
  171.                (setq start (match-beginning 0)
  172.                      end (match-end 0)
  173.                      word (buffer-substring start end)))
  174.          (set-syntax-table current-syntax))
  175.       (ispell-init-process)   ;; erases ispell output buffer
  176.       (or quietly (message "Checking spelling of %s..." (upcase word)))
  177.       (save-excursion
  178.          (set-buffer ispell-out-name)
  179.          (send-string ispell-process (concat word "\n"))
  180.          (while (progn                                         ;; Wait until we have a complete line
  181.                    (goto-char (point-max))
  182.                    (/= (preceding-char) ?\n))
  183.             (accept-process-output ispell-process))
  184.          (goto-char (point-min))
  185.          (setq poss (ispell-parse-output
  186.                        (buffer-substring (point) 
  187.                                          (progn (end-of-line) (point))))))
  188.       (cond ((eq poss t)
  189.              (or quietly (message "Checking spelling of %s... correct" (upcase word))))
  190.             ((stringp poss)
  191.              (or quietly (message "Checking spelling of %s... correct (derived from %s)" (upcase word) (upcase poss))))
  192. ;           ((null poss)
  193. ;            (or quietly (message "Checking spelling of %s... not found" (upcase word))))
  194.             (t (setq replace (ispell-choose poss word))
  195.                (if replace
  196.                    (progn
  197.                       (goto-char end)
  198.                       (delete-region start end)
  199.                       (insert-string replace)))))
  200.       poss))
  201.  
  202.  
  203. (defun ispell-choose (choices word)
  204.   "Display possible corrections from list CHOICES.  Return chosen word
  205. if one is chosen, or nil to keep original WORD."
  206.   (unwind-protect 
  207.       (save-window-excursion
  208.     (let ((count 0)
  209.           (line 2)
  210.           (words choices)
  211.           (window-min-height 2)
  212.           char num result)
  213.       (save-excursion
  214.         (set-buffer (get-buffer-create " *Choices*")) (erase-buffer)
  215.         (setq mode-line-format (concat "--  %b (Type number to select replacement for "
  216.                                            (upcase word)
  217.                                            ")  --"))
  218.         (while words
  219.           (if (<= (+ 7 (current-column) (length (car words)))
  220.               (window-width))
  221.           nil
  222.         (insert "\n")
  223.         (setq line (1+ line)))
  224.           (insert "(" (+ count ?0) ") " (car words) "  ")
  225.           (setq words (cdr words)
  226.             count (1+ count)))
  227.             (if (= count 0) (insert "(none)")))
  228.       (overlay-window line)
  229.       (switch-to-buffer " *Choices*")
  230.       (select-window (next-window))
  231.       (while (eq t
  232.              (setq result
  233.                (progn
  234.                  (message "%s: a(dd), c(orrect), r(eplace), space or s(kip) [default], ? (help)" (upcase word)) ; q(uit)
  235.                  (setq char (read-char))
  236.                  (setq num (- char ?0))
  237.                  (cond ((or (= char ? ) (= char ?s))           ; Skip for this invocation
  238.                                     (ispell-ignore-later-occurrences word)
  239.                                     nil)
  240.                    ((= char ?a)                            ; Add to dictionary
  241.                      (send-string ispell-process
  242.                           (concat "*" word "\n"))
  243.                     (send-string ispell-process            ; Because ispell isn't reinitialized
  244.                         (concat "@" word "\n"))
  245.                                     (ispell-ignore-later-occurrences word)
  246.                     nil)
  247.                    ((= char ?c)                           ; Assume correct but don't add to dict
  248.                     (send-string ispell-process
  249.                         (concat "@" word "\n"))
  250.                                     (ispell-ignore-later-occurrences word)
  251.                     nil)
  252.                    ((= char ?r)                           ; Query replace
  253.                                     (ispell-ignore-later-occurrences word)
  254.                                     (read-string (format "Replacement for %s: " (upcase word)) nil))
  255.                    ((and (>= num 0) (< num count))
  256.                                     (ispell-ignore-later-occurrences word)
  257.                                     (nth num choices))
  258.                    ((= char ?\C-r)                        ; Note: does not reset syntax table
  259.                     (save-excursion (recursive-edit)) t)  ; Dangerous
  260. ;                   ((= char ?\C-z)
  261. ;                    (suspend-emacs) t)
  262.                    ((or (= char help-char) (= char ?\?))
  263.                                     (message "a(dd to dict), c(orrect for this session), r(eplace with your word), or number of replacement")
  264.                     (sit-for 3) t)
  265.                    (t (ding) t))))))
  266.       result))
  267.     ;; Protected forms...
  268.     (bury-buffer " *Choices*")))
  269.  
  270. (defun ispell-ignore-later-occurrences (word)
  271.    (if (get-buffer ispell-temp-name)
  272.        (save-excursion
  273.           (set-buffer ispell-temp-name)
  274.           (save-excursion
  275.              (replace-regexp (concat "^" word "$")
  276.                              (concat "+" word))))))
  277.  
  278. (defun overlay-window (height)
  279.   "Create a (usually small) window with HEIGHT lines and avoid
  280. recentering."
  281.   (save-excursion
  282.     (let ((oldot (save-excursion (beginning-of-line) (dot)))
  283.       (top (save-excursion (move-to-window-line height) (dot)))
  284.       newin)
  285.       (if (< oldot top) (setq top oldot))
  286.       (setq newin (split-window-vertically height))
  287.       (set-window-start newin top))))
  288.  
  289.  
  290. (defvar ispell-process nil
  291.   "Holds the process object for 'ispell'")
  292.  
  293. (defun ispell-parse-output (output)
  294. "Parse the OUTPUT string of 'ispell' and return either t for an exact
  295. match, a string containing the root word for a match via suffix
  296. removal, a list of possible correct spellings, or nil for a complete
  297. miss."
  298.   (cond
  299.    ((string= output "*") t)
  300.    ((string= output "#") nil)
  301.    ((string= (substring output 0 1) "+")
  302.     (substring output 2))
  303.    (t
  304.     (let ((choice-list '()))
  305.       (while (not (string= output ""))
  306.     (let* ((start (string-match "[A-z]" output))
  307.            (end (string-match " \\|$" output start)))
  308.       (if start
  309.           (setq choice-list (cons (substring output start end)
  310.                       choice-list)))
  311.       (setq output (substring output (1+ end)))))
  312.       choice-list))))
  313.  
  314.  
  315. (defun ispell-init-process ()
  316.    "Check status of 'ispell' process and start if necessary."
  317.    (if (and ispell-process
  318.             (eq (process-status ispell-process) 'run))
  319.        (save-excursion
  320.           (set-buffer ispell-out-name)
  321.           (erase-buffer))
  322.        (if ispell-process
  323.            (message "Restarting dead ispell process...")
  324.            (message "Starting new ispell process..."))
  325.        (ispell-check-version-compatibility)
  326.        (if (get-buffer ispell-out-name) (kill-buffer ispell-out-name))
  327.        (setq ispell-process
  328. ;;           (let ((process-connection-type nil)) ; Don't use pty
  329.                 (apply 'start-process "ispell"
  330.                        ispell-out-name ispell-program-name
  331.                        (if ispell-dictionary
  332.                            (list "-p" ispell-dictionary "-A")
  333.                            (list "-A")))
  334. ;;              )
  335.              )
  336.        (process-kill-without-query ispell-process)
  337.        (sit-for 3)))
  338.  
  339. (defun ispell-check-version-compatibility ()
  340.    (let ((buffer (get-buffer-create ispell-out-name)))
  341.       (save-excursion
  342.          (set-buffer buffer)
  343.          (erase-buffer)
  344.          (call-process ispell-program-name nil t nil "-v")
  345.          (goto-char (point-min))
  346.          (if (search-forward ispell-version nil t)
  347.              t
  348.              (if (search-forward "Version " nil 'move)
  349.                  (error "Incompatible version of %s (expected %s, but \"%s -v\" returned %s)"
  350.                         ispell-program-name
  351.                         ispell-version
  352.                         ispell-program-name
  353.                         (buffer-substring (point)
  354.                                           (progn (re-search-forward "[^0-9.]" nil 'move) (- (point) 1))))
  355.                  (error "Old version of %s (doesn't handle -v option)" ispell-program-name))))))
  356.  
  357. ; For TeX users, try "detex -iw" or "detex -iw | tr -cs A-Za-z \012".  Note
  358. ; that the output of the filter must be one word per line.
  359.  
  360. (defvar ispell-filter-hook "tr"
  361.   "*Filter to pass a region through before sending it to ispell.
  362. Must produce output one word per line.  Typically this is set to tr,
  363. deroff, detex, etc.")
  364. (make-variable-buffer-local 'ispell-filter-hook)
  365.  
  366. (defvar ispell-filter-hook-args '("-cs" "A-Za-z" "\012")
  367.   "*Argument LIST to pass to ispell-filter-hook")
  368. (make-variable-buffer-local 'ispell-filter-hook-args)
  369.  
  370. (defvar ispell-filter-hook-produces-single-column t
  371.    "*This is nil if your ispell-filter-hook does not output one word per line.")
  372.  
  373. ; This routine has certain limitations brought about by the filter
  374. ; hook.  For example, deroff will take ``\fBcat\fR'' and spit out
  375. ; ``cat''.  This is hard to search for since word-search-forward will
  376. ; not match at all and search-forward for ``cat'' will match
  377. ; ``concatenate'' if it happens to occur before.
  378. ; `ispell-region' filters the region into `*ispell-temp*', writes the
  379. ; buffer to a temporary file, and sends a ``&Include_File&foobar''
  380. ; string to the ispell process which is writing into `*ispell*'.
  381. ; `ispell-region' then searches `*ispell*' for a spelling error (`#' or
  382. ; `&'), checks the `*ispell-temp*' buffer for the misspelled word and
  383. ; then skips forward `count' words (the number of correct lines in
  384. ; `*ispell*') in the region.  It then searches for the misspelled
  385. ; word.  This is not a foolproof heuristic but it is fast and works
  386. ; most of the time.
  387. ; ... with the unfortunate side-effect that it will sometimes
  388. ; pick up the same string in other words too (e.g. if you had the word "food"
  389. ; near the "\fIfoo\fP" that you were looking for).
  390. ; Another disadvantage is that your "prefobnicator" (deroff or detex or
  391. ; whatever) can't delete too many words (and you can't run it through spell(1)
  392. ; to cut down on the number of words you want checked) because of the way this
  393. ; hack works.
  394. ; To get around this, you can setq the variable ispell-words-have-boundaries to
  395. ; t (for normal cases) and nil (for embedded-word texts such as for nroff/troff).
  396. ; In the first case, your prefobnicator can, for instance, do a "ispell -l" to cut
  397. ; down on the number of words you need to "ispell -a" (increasing the program's
  398. ; speed considerably).
  399.  
  400. (defun ispell-region (start end)
  401.    "Check a region for spelling errors interactively.  The variable
  402. which should be buffer or mode specific ispell-filter-hook is called
  403. to filter out text processing commands."
  404.    (interactive "r")
  405.    (let ((this-buf (current-buffer))
  406.          (spell-file (make-temp-name "/tmp/ispell"))
  407.          (spell-buf (get-buffer-create ispell-temp-name))
  408.          (current-syntax (syntax-table))
  409.          (tracker 1)
  410.          word poss replace endbound ispell-out)
  411.       (ispell-init-process)
  412.       (setq ispell-out (get-buffer ispell-out-name))
  413.       (unwind-protect
  414.          (save-excursion
  415.             (save-restriction
  416.                (message "Prefrobnicating...")
  417.                (set-buffer this-buf)
  418.                (narrow-to-region start end)
  419.                (sit-for 0)
  420.                (set-syntax-table ispell-syntax-table)
  421.                (set-buffer spell-buf)
  422.                (erase-buffer)
  423.                (set-buffer this-buf)
  424.                (apply 'call-process-region 
  425.                       (append (list start end ispell-filter-hook nil spell-buf nil)
  426.                               ispell-filter-hook-args))
  427.                (goto-char start)
  428.                (set-buffer spell-buf)
  429.                (if (not ispell-filter-hook-produces-single-column)
  430.                    (call-process-region (point-min) (point-max) "tr" t t nil "-cs" "A-Za-z" "\012")) ;; Make single column.
  431.                (goto-char (point-max))
  432.                (and (/= (preceding-char) ?\n) ; couple of hacks for tr
  433.                     (insert "\n"))
  434.                (goto-char (point-min))
  435.                (while (= (following-char) ?\n)
  436.                   (delete-char 1))
  437.                (write-region (point-min) (point-max) spell-file nil 1)
  438.                (send-string ispell-process 
  439.                             (concat "&Include_File&" spell-file "\n"))
  440.                (message "Looking for a misspelled word... (status: %s)" (process-status ispell-process))
  441.                (sit-for 0)
  442.                (while (and (not (eobp))
  443.                            (eq (process-status ispell-process) 'run))
  444.                   (set-buffer ispell-out)
  445.                   (goto-char (point-max))
  446.                   (beginning-of-line)
  447.                   (setq endbound (point))
  448.                   (goto-char tracker)
  449.                   (if (prog1
  450.                          (not (re-search-forward "^[#&]" endbound 1))
  451.                          (beginning-of-line)
  452.                          (setq count (count-lines tracker (point))
  453.                                tracker (point))
  454.                          (set-buffer spell-buf)
  455.                          (forward-line count)
  456.                          (message "Looking for a misspelled word... (status: %s)"  ;; "(status: %s, at: %s, #%s)"
  457.                                   (process-status ispell-process)
  458. ;;                                (upcase (buffer-substring (point) (save-excursion (end-of-line) (point))))
  459. ;;                                (count-lines (point-min) (point))
  460.                                   ))
  461.                       (if (not (eobp)) ;; Needed for Sun 260's because of timing errors.
  462.                           (accept-process-output ispell-process))
  463.                       (setq word (buffer-substring (point)
  464.                                                    (progn (end-of-line) (point))))
  465.                       (forward-char 1)
  466.                       (set-buffer ispell-out) ; (goto-char tracker)
  467.                       (setq poss (ispell-parse-output
  468.                                   (buffer-substring (point) 
  469.                                                     (progn (end-of-line) (point)))))
  470.                       (forward-char 1)
  471.                       (setq tracker (point))
  472.                       (set-buffer this-buf)
  473.                       (re-search-forward "\\W*\\(\\w+\\)" nil t (1- count)) ; get close
  474.                       (if (string= "+" (substring word 0 1))
  475.                           (search-forward (substring word 1) nil t)
  476.                           (if (re-search-forward (if ispell-words-have-boundaries
  477.                                                   (concat "\\b" (regexp-quote word) "\\b")
  478.                                                   (regexp-quote word))
  479.                                                  nil t)
  480.                               (let ((end (point)))
  481.                                  (search-backward word nil t)
  482.                                  (save-excursion
  483.                                     (let ((start (point)))
  484.                                        (recenter (/ (window-height) 2)) ; show word in context
  485.                                        (sit-for 0)
  486.                                        (if ispell-highlight (highlight-region start end))
  487.                                        (setq replace (ispell-choose poss word))
  488.                                        (if ispell-highlight (unhighlight-region start end))))
  489.                                  (if replace
  490.                                      (save-excursion
  491.                                         (query-replace-regexp (if ispell-words-have-boundaries
  492.                                                                   (concat "\\b" (regexp-quote word) "\\b")
  493.                                                                   (regexp-quote word))
  494.                                                               replace))))
  495.                               (message "Can't find %s in original text -- Any key to continue" word)
  496.                               (read-char)
  497. ;;                            (and (= ?\C-z (read-char)) (suspend-emacs))
  498.                               )
  499.                           (message "Looking for a misspelled word... (status: %s)" (process-status ispell-process))
  500.                           (sit-for 0))
  501.                       (set-buffer spell-buf)))))
  502.          (if (eq (process-status ispell-process) 'run)
  503.              (message "Done.")
  504.              (message "Warning - ispell process died."))
  505.          (set-syntax-table current-syntax)
  506.          (and (file-exists-p spell-file)
  507.               (delete-file spell-file)))))
  508.  
  509. (defun ispell-buffer () 
  510.   "Check the current buffer for spelling errors interactively.  The variable
  511. which should be buffer or mode specific ispell-filter-hook is called to
  512. filter out text processing commands."
  513.   (interactive)
  514.   (ispell-region (point-min) (point-max)))
  515.  
  516.  
  517. ; In case you already have this, comment out the following:
  518.  
  519. (defun highlight-region (p1 p2)
  520.    "Highlight the current region.  You may have to rewrite this for your
  521. particular terminal."
  522.    (interactive "r")
  523.    (let ((s (buffer-substring p1 p2))
  524.          (inverse-video t))
  525.       (delete-region p1 p2)
  526.       (sit-for 0)
  527.       (insert s)
  528.       (sit-for 0)))
  529.  
  530. (defun unhighlight-region (p1 p2)
  531.    "Unhighlight the current region.  See highlight-region."
  532.    (interactive "r")
  533.    (let ((s (buffer-substring p1 p2))
  534.          (inverse-video nil))
  535.       (delete-region p1 p2)
  536.       (sit-for 0)
  537.       (insert s)
  538.       (sit-for 0)))
  539.  
  540.  
  541. ;; Interactive word completion.
  542. ;; Some code and many ideas tweaked from Peterson's spell-dict.el.
  543. ;; Ashwin Ram <Ram@yale>, 8/14/87.
  544.  
  545. (defvar ispell-words-file "/usr/dict/words"
  546.    "*File used for ispell-complete-word command.  On 4.3bsd systems, try
  547. using \"/usr/dict/web2\" for a larger selection.  Apollo users may want to
  548. try \"/sys/dict\".")
  549.  
  550. (defun ispell-complete-word ()
  551.    "Look up word before point in dictionary (see the variable
  552. ispell-words-file) and try to complete it.  If in the middle of a word,
  553. replace the entire word."
  554.    (interactive)
  555.    (let* ((current-word (buffer-substring (save-excursion (backward-word 1) (point))
  556.                                           (point)))
  557.           (in-word (looking-at "\\w"))
  558.           (possibilities (save-excursion
  559.                             (set-buffer (get-buffer-create ispell-temp-name))
  560.                             (erase-buffer)
  561.                             (or (string= current-word "") ; Will give you every word in the dictionary!
  562.                                 (call-process "look" nil t nil "-df" current-word ispell-words-file))
  563.                             (if (> (buffer-size ) 0)
  564.                                 (ispell-parse-output (buffer-string))
  565.                                 '())))
  566.           (replacement (ispell-choose possibilities current-word)))
  567.       (cond (replacement
  568.              (if in-word (kill-word 1))        ;; Replace the whole word.
  569.              (search-backward current-word)
  570.              (replace-match replacement)))))   ;; To preserve capitalization etc.
  571.  
  572.